package edu.iscas.appcheckclient.model.actions;

import edu.iscas.appcheckclient.model.Selector;

public class Check extends ParamAction {

    public static final String jsonName = "assert";
    protected boolean positive;
    protected Selector selector;
    protected long time;
    protected Check.Type type;

    public enum Type {
        Checked, Clickable, CompletelyDisplayed, Displayed,
        Enabled, Focusable, Focused, SupportsIME,
        Text, TextStartsWith, TextEndsWith, TextContains, TextAsVar
    }

    public Check(Check.Type type, Selector selector, boolean positive) {
        this.name = "assert";
        this.type = type;
        this.selector = selector;
        this.positive = positive;
    }


    @Override
    public Selector getSelector() {
        return null;
    }

    @Override
    public void setStatement(String statement) {
        this.statement = statement;
    }

    @Override
    public String brewStatement(boolean paramBoolean) {
        String str;
        switch (type){
            case Checked:
                str = this.positive ? "isChecked()" : "isNotChecked()";
                break;
            case Clickable:
                str = this.positive ? "isClickable()" : "Matchers.not(isClickable())";
                break;
            case CompletelyDisplayed:
                str = this.positive ? "isCompletelyDisplayed()" : "Matchers.not(isCompletelyDisplayed())";
                break;
            case Displayed:
                str = this.positive ? "isDisplayed()" : "Matchers.not(isDisplayed())";
                break;
            case Enabled:
                str = this.positive ? "isEnabled()" : "Matchers.not(isEnabled())";
                break;
            case Focusable:
                str = this.positive ? "isFocusable()" : "Matchers.not(isFocusable())";
                break;
            case Focused:
                str = this.positive ? "hasFocus()" : "Matchers.not(hasFocus())";
                break;
            case SupportsIME:
                str = this.positive ? "supportsImputMethods()" : "Matchers.not(supportsInputMethods())";
                break;
            case Text:
                str = "withText(\"" + getStringParam("text") + "\")";
                break;
            case TextStartsWith:
                str = "withText(startsWith(\"" + getStringParam("text") + "\"))";
                break;
            case TextEndsWith:
                str = "withText(endsWith(\"" + getStringParam("text") + "\"))";
                break;
            case TextContains:
                str = "withText(containsString(\"" + getStringParam("text") + "\"))";
                break;
            case TextAsVar:
                str = "String " + getStringParam("variable") + " = fetchText(" + this.selector.brewStatement(paramBoolean) + ")";
                return str;
            default:
                return null;
        }
        return "onView(" + this.selector.brewStatement(paramBoolean) + ").check(matches(" + str + "))";
    }

    @Override
    public String getTypeString() {
        return "assert" + getType().toString();
    }

    @Override
    public String getValue() {
        if(getSelector() != null){
            return  getSelector().getValue();
        }
        return "";
    }

    public boolean isPositive() {
        return positive;
    }

    public long getTime() {
        return time;
    }

    public Type getType() {
        return type;
    }


    @Override
    public boolean equals(Object o) {
        if(!(o instanceof Check)){
            return false;
        }
        Check paramObject = (Check)o;
        if ((!this.name.equals(paramObject.name)) || (!getType().equals(paramObject.getType())) ||
                (((this.params == null) || (!this.params.equals(paramObject.params))) &&
                        ((this.params != paramObject.params) ||
                                (((this.selector == null) || (!this.selector.equals(paramObject.selector))) &&
                                        ((this.selector != paramObject.selector) || (this.positive != paramObject.positive) || (this.time != paramObject.time)))))){
            return false;
        }
        return true;
    }
}
